home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / nhclb120.zoo / nr3.c < prev    next >
C/C++ Source or Header  |  1992-06-18  |  26KB  |  983 lines

  1. /* net/rom level 3 low level processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "iface.h"
  10. #include "timer.h"
  11. #include "arp.h"
  12. #include "slip.h"
  13. #include "ax25.h"
  14. #include "netrom.h"
  15. #include "nr4.h"
  16. #include "lapb.h"
  17. #include <ctype.h>
  18. #ifdef    UNIX
  19. #include <string.h>
  20. #include <memory.h>
  21. #endif
  22.  
  23. static struct nr_bind *find_best();
  24.  
  25. /* Nodes message broadcast address: "NODES" in shifted ASCII */
  26. struct ax25_addr nr_nodebc = {
  27.     'N'<<1, 'O'<<1, 'D'<<1, 'E'<<1, 'S'<<1, ' '<<1,
  28.     ('0'<<1) | E
  29. } ;
  30.  
  31. struct nriface nrifaces[NRNUMIFACE] ;
  32. unsigned nr_numiface ;
  33. struct nrnbr_tab *nrnbr_tab[NRNUMCHAINS] ;
  34. struct nrroute_tab *nrroute_tab[NRNUMCHAINS] ;
  35. struct nrnf_tab *nrnf_tab[NRNUMCHAINS] ;
  36. unsigned nr_nfmode = NRNF_NOFILTER ;
  37. unsigned nr_ttl = 64 ;
  38. unsigned obso_init = 6 ;
  39. unsigned obso_minbc = 5 ;
  40. unsigned nr_maxroutes = 5 ;
  41. unsigned nr_autofloor = 1 ;
  42. unsigned nr_verbose = 0 ;
  43. struct interface *nr_interface ;
  44.  
  45. /* send a NET/ROM layer 3 datagram */
  46. void nr3output(dest, data)
  47. struct ax25_addr *dest ;
  48. struct mbuf *data ;
  49. {
  50.     struct nr3hdr n3hdr ;
  51.     struct mbuf *n3b ;
  52.  
  53.     n3hdr.dest = *dest ;    /* copy destination field */
  54.     n3hdr.ttl = nr_ttl ;    /* time to live from initializer parm */
  55.  
  56.     if ((n3b = htonnr3(&n3hdr)) == NULLBUF) {
  57.         free_p(data) ;
  58.         return ;
  59.     }
  60.  
  61.     append(&n3b, data) ;
  62.  
  63.     /* The null interface indicates that the packet needs to have */
  64.     /* an appropriate source address inserted by nr_route */
  65.     
  66.     nr_route(n3b,NULLAX25) ;
  67. }
  68.  
  69.  
  70. /* send IP datagrams across a net/rom network connection */
  71. /*ARGSUSED*/
  72. int
  73. nr_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  74. struct mbuf *bp ;
  75. struct interface *interface ;
  76. int32 gateway ;
  77. char precedence ;
  78. char delay ;
  79. char throughput ;
  80. char reliability ;
  81. {
  82.     struct ax25_addr dest ;
  83.     struct mbuf *pbp ;
  84.     struct nr4hdr n4hdr ;
  85.     char *hwaddr ;
  86.     struct arp_tab *arp ;
  87.  
  88.     if ((arp = arp_lookup(ARP_NETROM,gateway)) == NULLARP) {
  89.         free_p(bp) ;    /* drop the packet if no route */
  90.         return ;
  91.     }
  92.     hwaddr = arp->hw_addr ;                /* points to destination */
  93.     memcpy(dest.call, hwaddr, ALEN) ;
  94.     dest.ssid = hwaddr[ALEN] ;
  95.         
  96.     /* Create a "network extension" transport header */
  97.     n4hdr.opcode = NR4OPPID ;
  98.     n4hdr.u.pid.family = PID_IP ;
  99.     n4hdr.u.pid.proto = PID_IP ;
  100.  
  101.     if ((pbp = htonnr4(&n4hdr)) == NULLBUF) {
  102.         free_p(bp) ;
  103.         return ;
  104.     }
  105.  
  106.     append(&pbp,bp) ;        /* Append the data to that */
  107.     nr3output(&dest, pbp) ; /* and pass off to level 3 code */
  108.  
  109. }
  110.  
  111. /* Figure out if a call is assigned to one of my net/rom
  112.  * interfaces.
  113.  */
  114. static int
  115. ismycall(addr)
  116. struct ax25_addr *addr ;
  117. {
  118.     register int i ;
  119.     int found = 0 ;
  120.     
  121.     for (i = 0 ; i < nr_numiface ; i++)
  122.         if (addreq((struct ax25_addr *)(nrifaces[i].interface->hwaddr),
  123.             addr)) {
  124.             found = 1 ;
  125.             break ;
  126.         }
  127.  
  128.     return found ;
  129. }
  130.  
  131.  
  132. /* Route net/rom network layer packets.
  133.  */
  134. nr_route(bp, iaxp)
  135. struct mbuf *bp ;            /* network packet */
  136. struct ax25_cb *iaxp ;        /* incoming ax25 control block */
  137. {
  138.     struct nr3hdr n3hdr ;
  139.     struct nr4hdr n4hdr ;
  140.     struct ax25_cb *axp, *find_ax25(), *open_ax25() ;
  141.     struct ax25 naxhdr ;
  142.     struct ax25_addr neighbor, from ;
  143.     struct mbuf *hbp, *pbp ;
  144.     extern int16 axwindow ;
  145.     void ax_incom(), nr4input() ;
  146.     register struct nrnbr_tab *np ;
  147.     register struct nrroute_tab *rp ;
  148.     register struct nr_bind *bindp ;
  149.     struct nr_bind *find_best() ;
  150.     struct interface *interface ;
  151.     unsigned ifnum ;
  152.     
  153.     if (ntohnr3(&n3hdr,&bp) == -1) {
  154.         free_p(bp) ;
  155.         return ;
  156.     }
  157.  
  158.     /* If this isn't an internally generated network packet,
  159.      * give the router a chance to record a route back to the
  160.      * sender, in case they aren't in the local node's routing
  161.      * table yet.
  162.      */
  163.  
  164.     if (iaxp != NULLAX25) {
  165.         /* find the interface number */
  166.         for (ifnum = 0 ; ifnum < nr_numiface ; ifnum++)
  167.             if (iaxp->interface == nrifaces[ifnum].interface)
  168.                 break ;
  169.  
  170.         if (ifnum == nr_numiface) {    /* shouldn't happen! */
  171.             free_p(bp) ;
  172.             return ;
  173.         }
  174.  
  175.         from = iaxp->addr.dest ;
  176.         from.ssid |= E ;
  177.  
  178.         /* Add (possibly) a zero-quality recorded route via */
  179.         /* the neighbor from which this packet was received */
  180.         /* Note that this doesn't work with digipeated neighbors, */
  181.         /* at this point. */
  182.         
  183.         (void) nr_routeadd("      ",&n3hdr.source,ifnum,0,
  184.                                     (char *)&from,0,1) ;
  185.     }
  186.  
  187.     /* A packet from me, to me, can only be one thing: */
  188.     /* a horrible routing loop.  This will probably result */
  189.     /* from a bad manual ARP entry, but we should fix these */
  190.     /* obscure errors as we find them. */
  191.     
  192.     if (ismycall(&n3hdr.dest)) {
  193.         if (iaxp == NULLAX25) {        /* From me? */
  194.             free_p(bp) ;
  195.             return ;
  196.         } else {                    /* It's from somewhere else! */
  197.             if (ntohnr4(&n4hdr,&bp) == -1) {
  198.                 free_p(bp) ;
  199.                 return ;
  200.             }
  201.             if ((n4hdr.opcode & NR4OPCODE) == 0) {
  202.                 if (n4hdr.u.pid.family == PID_IP
  203.                     && n4hdr.u.pid.proto == PID_IP)
  204.                     ip_route(bp,0) ;
  205.                 else                     /* we don't do this proto */
  206.                     free_p(bp) ;
  207.  
  208.                 return ;
  209.             }
  210.             
  211.             /* Must be net/rom transport: */
  212.  
  213.             nr4input(&n4hdr,bp) ;
  214.  
  215.         }
  216.         return ;
  217.     }
  218.  
  219.     if ((rp = find_nrroute(&n3hdr.dest)) == NULLNRRTAB) {
  220.         /* no route, drop the packet */
  221.         free_p(bp) ;
  222.         return ;
  223.     }
  224.  
  225.     if ((bindp = find_best(rp->routes,1)) == NULLNRBIND) {
  226.         /* This shouldn't happen yet, but might if we add */
  227.         /* dead route detection */
  228.         free_p(bp) ;
  229.         return ;
  230.     }
  231.  
  232.     np = bindp->via ;
  233.     memcpy(neighbor.call,np->call,ALEN) ;
  234.     neighbor.ssid = np->call[ALEN] ;
  235.     interface = nrifaces[np->interface].interface ;
  236.  
  237.     /* Now check to see if iaxp is null.  That is */
  238.     /* a signal that the packet originates here, */
  239.     /* so we need to insert the callsign of the appropriate  */
  240.     /* interface */
  241.     if (iaxp == NULLAX25)
  242.         memcpy((char *)&n3hdr.source,interface->hwaddr,AXALEN) ;
  243.     
  244.     /* Make sure there is a connection to the neighbor */
  245.     if ((axp = find_ax25(&neighbor)) == NULLAX25 ||
  246.         (axp->state != CONNECTED && axp->state != RECOVERY)) {
  247.         /* Open a new connection or reinitialize old one */
  248.         /* hwaddr has been advanced to point to neighbor + digis */
  249.         atohax25(&naxhdr, np->call, (struct ax25_addr *)interface->hwaddr) ;
  250.         axp = open_ax25(&naxhdr, axwindow, ax_incom, NULLVFP, NULLVFP,
  251.                         interface,(char *)0) ;
  252.         if (axp == NULLAX25) {
  253.             free_p(bp) ;
  254.             return ;
  255.         }
  256.     }
  257.         
  258.     if (--n3hdr.ttl == 0) {    /* the packet's time to live is over! */
  259.         free_p(bp) ;
  260.         return ;
  261.     }
  262.  
  263.     /* allocate and fill PID mbuf */
  264.     if ((pbp = alloc_mbuf(1)) == NULLBUF) {
  265.         free_p(bp) ;
  266.         return ;
  267.     }
  268.     pbp->cnt = 1 ;
  269.     *pbp->data = (PID_FIRST | PID_LAST | PID_NETROM) ;
  270.  
  271.     /* now format network header */
  272.     if ((hbp = htonnr3(&n3hdr)) == NULLBUF) {
  273.         free_p(pbp) ;
  274.         free_p(bp) ;
  275.         return ;
  276.     }
  277.  
  278.     append(&pbp,hbp) ;        /* append header to pid */
  279.     append(&pbp,bp) ;        /* append data to header */
  280.     send_ax25(axp,pbp) ;    /* pass it off to ax25 code */
  281. }
  282.     
  283.  
  284. /* Perform a nodes broadcast on interface # ifno in the net/rom
  285.  * interface table.
  286.  */
  287.  
  288. nr_bcnodes(ifno)
  289. unsigned ifno ;
  290. {
  291.     struct mbuf *hbp, *dbp, *savehdr ;
  292.     struct nrroute_tab *rp ;
  293.     struct nrnbr_tab *np ;
  294.     struct nr_bind * bp ;
  295.     struct nr3dest nrdest ;
  296.     int i, didsend = 0, numdest = 0 ;
  297.     register char *cp ;
  298.     struct interface *axif = nrifaces[ifno].interface ;
  299.     struct nr_bind *find_best() ;
  300.     
  301.     /* prepare the header */
  302.     if ((hbp = alloc_mbuf(NR3NODEHL)) == NULLBUF)
  303.         return ;
  304.         
  305.     hbp->cnt = NR3NODEHL ;    
  306.     
  307.     *hbp->data = NR3NODESIG ;
  308.     memcpy(hbp->data+1,nrifaces[ifno].alias,ALEN) ;
  309.  
  310.     /* Some people don't want to advertise any routes; they
  311.      * just want to be a terminal node.  In that case we just
  312.      * want to send our call and alias and be done with it.
  313.      */
  314.  
  315.     if (!nr_verbose) {
  316.         (*axif->output)(axif, (char *)&nr_nodebc, axif->hwaddr,
  317.                          (PID_FIRST | PID_LAST | PID_NETROM),
  318.                          hbp) ;    /* send it */
  319.         return ;
  320.     }
  321.     
  322.     /* make a copy of the header in case we need to send more than */
  323.     /* one packet */
  324.     savehdr = copy_p(hbp,NR3NODEHL) ;
  325.  
  326.     /* now scan through the routing table, finding the best routes */
  327.     /* and their neighbors.  create destination subpackets and append */
  328.     /* them to the header */
  329.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  330.         for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  331.             /* look for best, non-obsolescent route */
  332.             if ((bp = find_best(rp->r